package org.metasketch.editor.toolbox;

import java.util.ArrayList;
import java.util.List;

import javafx.scene.Node;

import org.metasketch.diagram.javafx.graphics.BaseLink;
import org.metasketch.editor.Project;
import org.metasketch.editor.links.ILink;
import org.metasketch.editor.project.CommonProject;
import org.metasketch.graphics.BaseGraphic;
import org.metasketch.graphics.Diagram;
import org.metasketch.graphics.GraphicContainer;
import org.metasketch.graphics.GraphicLink;
import org.metasketch.graphics.GraphicNode;
import org.metasketch.graphics.registry.GraphicsRegistry;
import org.metasketch.graphics.registry.IGraphic;
import org.metasketch.javafx.graphics.JFXDiagram;
import org.metasketch.model.BaseModel;
import org.metasketch.model.CommonIdentified;

public class DefaultDiagramBuilder implements IDiagramBuilder {

	private SimpleToolBaseDiagramType diagramType;

	public DefaultDiagramBuilder() {

	}

	@Override
	public JFXDiagram getJFXDiagram(Diagram diagram, Project project)
			throws Throwable {

		CommonProject demoProject = (CommonProject) project;
		BaseModel model = demoProject.getModel();

		GraphicsRegistry registry = diagramType.getGraphicsRegistry();

		JFXDiagram jfxDiagram = new JFXDiagram();
		jfxDiagram.setDiagram(diagram);
		jfxDiagram.setModel(model);
		jfxDiagram.setInputHandler(diagramType.getInputHandler());

		List<Node> nodes = new ArrayList<Node>();

		List<GraphicLink> links = new ArrayList<GraphicLink>();

		List<BaseGraphic> graphics = diagram.getGraphics();
		for (BaseGraphic graphic : graphics) {

			if (graphic instanceof GraphicLink) {
				links.add((GraphicLink) graphic);
				continue;
			}

			String graphicType = graphic.getType();
			IGraphic jfxGraphic = registry.get(graphicType);
			// TODO if no graphic was found for that graphicType, then throw an
			// exception...

			CommonIdentified semantic = model.getIndex().getById(
					graphic.getSemantic());

			// Instantiate and what not...
			jfxGraphic.setup(graphic, semantic, diagram, model);

			// Node node

			nodes.add((Node) jfxGraphic);

			// TODO recursify this

			recursiveContainer(diagram, model, registry, jfxDiagram, graphic,
					jfxGraphic, links);

		}

		jfxDiagram.addNodes(nodes);

		// now work on the links..
		nodes.clear();
		for (GraphicLink graphicLink : links) {
			String graphicType = graphicLink.getType();
			IGraphic jfxGraphic = registry.get(graphicType);
			BaseLink baseLink = (BaseLink) jfxGraphic;
			// TODO if no graphic was found for that graphicType, then throw an
			// exception...

			CommonIdentified semantic = model.getIndex().getById(
					graphicLink.getSemantic());

			org.metasketch.diagram.javafx.graphics.BaseGraphic source = null, target = null;

			if (graphicLink.getSource() != null) {
				source = (org.metasketch.diagram.javafx.graphics.BaseGraphic) jfxDiagram
						.getBaseGraphicPerId(graphicLink.getSource());
			}

			if (graphicLink.getTarget() != null) {
				target = (org.metasketch.diagram.javafx.graphics.BaseGraphic) jfxDiagram
						.getBaseGraphicPerId(graphicLink.getTarget());
			}

			ILink link = diagramType.getLinkRegistry().get(graphicType);

			// Point start = graphicLink.getPoints().get(0);
			// Point end = graphicLink.getPoints().get(1);

			baseLink.setLink(link);
			baseLink.setSource(source);
			baseLink.setTarget(target);
			// baseLink.setP

			// Instantiate and what not...
			baseLink.setup(graphicLink, semantic, diagram, model);

			// Node node

			nodes.add((Node) baseLink);
		}

		jfxDiagram.addNodes(nodes);

		return jfxDiagram;

	}

	private void recursiveContainer(Diagram diagram, BaseModel model,
			GraphicsRegistry registry, JFXDiagram jfxDiagram,
			BaseGraphic graphic, IGraphic jfxGraphic, List<GraphicLink> links)
			throws Throwable {

		if (graphic instanceof GraphicContainer) {

			GraphicContainer container = (GraphicContainer) graphic;
			List<BaseGraphic> children = container.getNodes();

			for (BaseGraphic childGraphic : children) {

				if (graphic instanceof GraphicLink) {
					links.add((GraphicLink) graphic);
					continue;
				}

				String childGraphicType = childGraphic.getType();
				IGraphic childJfxGraphic = registry.get(childGraphicType);
				// TODO if no graphic was found for that graphicType, then
				// throw an
				// exception...

				CommonIdentified childSemantic = model.getIndex().getById(
						childGraphic.getSemantic());

				// Instantiate and what not...
				childJfxGraphic.setup((GraphicNode) childGraphic,
						childSemantic, diagram, model);

				// Node node

				// nodes.add((Node) jfxGraphic);

				// parentContainer.addNode(node.getGraphicNode());
				((org.metasketch.diagram.javafx.graphics.BaseGraphic) jfxGraphic)
						.getChildren().add((Node) childJfxGraphic);
				jfxDiagram.addNodeListeners((Node) childJfxGraphic);

				recursiveContainer(diagram, model, registry, jfxDiagram,
						childGraphic, childJfxGraphic, links);

			}

		}
	}

	public SimpleToolBaseDiagramType getDiagramType() {
		return diagramType;
	}

	public void setDiagramType(SimpleToolBaseDiagramType diagramType) {
		this.diagramType = diagramType;
	}

}
